﻿using System;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace DynamicMVVM.Test
{
    [TestClass]
    public class DynamicViewModelUnitTest
    {
        private dynamic _testViewMode;

        [TestInitialize]
        public void Setup()
        {
            _testViewMode = new TestViewMode();
        }

        [TestMethod]
        public void TestGetCommandWithoutParameter()
        {
            _testViewMode.TestProperty = "CanExecuteWithoutParameter";
            var commandObject = _testViewMode.WithoutParameterCommand;
            Assert.IsInstanceOfType(commandObject, typeof(RelayCommand), "returned object should be RelayCommand");

            var canExecuteSaveCommand = commandObject.CanExecute(null);
            Assert.AreEqual(true,canExecuteSaveCommand, "CanExecute should be true");

            commandObject.Execute(null);
            Assert.AreEqual("WithoutParameterExecuted", _testViewMode.TestProperty, "Property value should be WithoutParameterExecuted");
        }

        [TestMethod]
        public void TestGetCommandWithParameters()
        {
            _testViewMode.TestProperty = "CanExecuteWithParameter";
            var model = new TestPerson()
                            {
                                FirstName = "Test",
                                LastName = "Method",
                                DateOfBirth = new DateTime(2000, 1, 1)
                            };

            _testViewMode.TestModel = model;

            var commandObject = _testViewMode.WithParameterCommand;
            Assert.IsInstanceOfType(commandObject, typeof(RelayCommand), "returned object should be RelayCommand");

            var canExecuteSaveCommand = commandObject.CanExecute(model);
            Assert.AreEqual(true, canExecuteSaveCommand, "CanExecute should be true");

            commandObject.Execute(model);
            Assert.AreEqual("WithParameterExecuted", _testViewMode.TestProperty, "Property value should be WithParameterExecuted");
        }

        [TestMethod]
        public void TestGetCommandWithGenericParameters()
        {
            _testViewMode.TestProperty = "CanExecuteWithGenericParameter";
            var model = new TestPerson()
            {
                FirstName = "Test",
                LastName = "Method",
                DateOfBirth = new DateTime(2000, 1, 1)
            };

            _testViewMode.TestModel = model;

            var commandObject = _testViewMode.WithGenericParameterCommand;
            Assert.IsInstanceOfType(commandObject, typeof(RelayCommand<TestPerson>), "returned object should be RelayCommand<TestPerson>");

            var canExecuteSaveCommand = commandObject.CanExecute(model);
            Assert.AreEqual(true, canExecuteSaveCommand, "CanExecute should be true");

            commandObject.Execute(model);
            Assert.AreEqual("WithGenericParameterExecuted", _testViewMode.TestProperty, "Property value should be WithParameterExecuted");
        }

        [TestMethod]
        public void TestGetCommandWithoutCanExecute()
        {
            _testViewMode.TestProperty = "WithoutCanExecuteMethod";
            var commandObject = _testViewMode.WithoutCanExecuteCommand;
            Assert.IsInstanceOfType(commandObject, typeof(RelayCommand), "returned object should be RelayCommand");

            var canExecuteSaveCommand = commandObject.CanExecute(null);
            Assert.AreEqual(true, canExecuteSaveCommand, "CanExecute should be true");

            commandObject.Execute(null);
            Assert.AreEqual("ExecutedWithoutCanExecuteMethod", _testViewMode.TestProperty, "Property value should be ExecutedWithoutCanExecuteMethod");
        }


    }

    internal class TestViewMode : DynamicViewModel
    {
        public string TestProperty { get; set; }

        public TestPerson TestModel { get; set; }

        public bool CanExecuteWithoutParameter()
        {
            return TestProperty == "CanExecuteWithoutParameter";
        }

        public void ExecuteWithoutParameter()
        {
            TestProperty = "WithoutParameterExecuted";
        }

        public bool CanExecuteWithParameter(object model)
        {
            if(model== null ||  model.GetType() != typeof(TestPerson))
            {
                return false;
            }
            return TestProperty == "CanExecuteWithParameter";
        }

        public void ExecuteWithParameter(object model)
        {
            if (model == null || model.GetType() != typeof(TestPerson))
            {
                throw  new InvalidDataException();
            }

            TestProperty = "WithParameterExecuted";
        }

        public bool CanExecuteWithGenericParameter(TestPerson model)
        {
            if (model == null)
            {
                return false;
            }

            return TestProperty == "CanExecuteWithGenericParameter";
        }

        public void ExecuteWithGenericParameter(TestPerson model)
        {
            if (model == null)
            {
                throw new InvalidDataException();
            }

            TestProperty = "WithGenericParameterExecuted";
        }

        public void ExecuteWithoutCanExecute()
        {
            TestProperty = "ExecutedWithoutCanExecuteMethod";
        }
    }
}